package com.biovr.backend.restcontroller;

import com.biovr.backend.domain.User;
import com.biovr.backend.repository.UserRepository;
import com.biovr.backend.utils.ResponseFactory;
import com.biovr.backend.utils.RestResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 在 @PreAuthorize 中我们可以利用内建的 SPEL 表达式：比如 'hasRole()' 来决定哪些用户有权访问。
 * 需注意的一点是 hasRole 表达式认为每个角色名字前都有一个前缀 'ROLE_'。所以这里的 'ADMIN' 其实在
 * 数据库中存储的是 'ROLE_ADMIN' 。这个 @PreAuthorize 可以修饰Controller也可修饰Controller中的方法。
 **/
@RestController
@RequestMapping("/users")
public class UserRestController {
    @Autowired
    private UserRepository repository;
    @Autowired
    private UserDetailsService userDetailsService;
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }
    /**
     * 得到所有用户
     * @return
     */
    @PreAuthorize("hasAnyRole('ADMIN','SUPER')")
    @RequestMapping(method = RequestMethod.GET)
    public  RestResponse<List<User>> getUsers() {
        return ResponseFactory.createSuccessResult( repository.findAll());
    }

    @PreAuthorize("hasAnyRole('ADMIN','SUPER')")
    @RequestMapping(method = RequestMethod.POST)
    RestResponse<User> addUser(@RequestBody User addedUser)  throws Exception{
        return ResponseFactory.createSuccessResult(repository.insert(addedUser));
    }

    @PostAuthorize("returnObject.data.username == principal.username or  hasAnyRole('ROLE_SUPER','ROLE_ADMIN')")
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public RestResponse<User> getUser(@PathVariable String id) {
        return ResponseFactory.createSuccessResult(repository.findOne(id)) ;
    }

    //@PreAuthorize("hasAnyRole('ADMIN','SUPER')")
    @PostAuthorize("returnObject.data.username == principal.username or  hasAnyRole('ROLE_SUPER','ROLE_ADMIN')")
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    RestResponse<User> updateUser(@PathVariable String id, @RequestBody User updatedUser) throws Exception {
        updatedUser.setId(id);
        return ResponseFactory.createSuccessResult(repository.save(updatedUser)) ;

    }
    @PostAuthorize("returnObject.data.username == principal.username or  hasAnyRole('ROLE_SUPER','ROLE_ADMIN')")
    @RequestMapping(value = "/pwd/check/{id}", method = RequestMethod.GET)
    RestResponse<?> checkPwd(@PathVariable String id, @RequestParam String pwd){
        User u = repository.findOne(id);
        if(u==null){
            return ResponseFactory.createErrorResult("无此用户");
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if(u.getPassword().equals(encoder.encode(pwd))){
            return ResponseFactory.createSuccessResult();
        }
        else{
            return ResponseFactory.createErrorResult("密码验证失败");
        }
    }

    /**
     * 修改密码
     * @param id
     * @param pwd
     * @return
     * @throws Exception
     */
    @PostAuthorize("returnObject.data.username == principal.username or  hasAnyRole('ROLE_SUPER','ROLE_ADMIN')")
    @PutMapping("/pwd/{id}")
    RestResponse<?> resetPwd(@PathVariable String id,@RequestParam String pwd) throws Exception{
        User u = repository.findOne(id);
        if(u==null){
            return ResponseFactory.createSuccessResult("无此用户");
        }

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        u.setPassword(encoder.encode(pwd));
        u.setLastPasswordResetDate(new Date());
        repository.save(u);
        return ResponseFactory.createSuccessResult("密码修改成功");
    }

    @PreAuthorize("hasAnyRole('ADMIN','SUPER')")
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    RestResponse<User> removeUser(@PathVariable String id) throws Exception{
        User deletedUser = repository.findOne(id);
        repository.delete(id);
        return ResponseFactory.createSuccessResult() ;
    }

    @PostAuthorize("returnObject.username == principal.username or hasRole('SUPER')")
    @RequestMapping(value = "/name/{username}",method = RequestMethod.GET)
    public User getUserByUsername(@PathVariable String username) {
        return repository.findByUsername(username);
    }

    @PreAuthorize("hasRole('SUPER')")
    @GetMapping("/roles")
    public RestResponse<List<User>> getUsersByRole(@RequestParam String role){
        return ResponseFactory.createSuccessResult(repository.findByRoles(role));
    }
}
